﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
using MVVM.Core;

namespace ObjectModel.Excel
{
    /// <summary>
    /// Holds serializable information about a range object's parent workbook and worksheet.
    /// </summary>
    public class OfflineSourceRange : OfflineRange, IConditionalRange, ILookUpStepRange
    {
        private readonly Application mApp = Globals.Application;
        private string mAddress = string.Empty;
        private string mAddressWithSheetName = string.Empty;
        private FileInfo mWorkbookFileInfo;
        private string mWorksheetName;
		private bool mWorkbookOpenedProgrammatically;
        private ConditionsCollection mConditions = new ConditionsCollection();

        public OfflineSourceRange() // Parameterless constructor required for serialization.
        {
        }
        
        public OfflineSourceRange(Range range)
        {
            Range = range;
        }

        public ConditionsCollection Conditions
        {
            get { return mConditions; }
            set { mConditions = value; }
        }

        public LookUpSteps LookUpSteps { get; set; }

        [XmlIgnore]
        public override Range Range
        {
            get
            {
                ApplyConditions();

            	return LookUpSteps != null ? LookUpSteps.ResolveInWorksheet(Worksheet) : GetRangeFromAddress();
            }

            set
			{
            	Workbook = value.Worksheet.Parent;
				base.Range = value;                
            }
        }

		protected override Range GetRangeFromAddress() {

			_Workbook prevActiveWorkbook = mApp.ActiveWorkbook;
			bool prevScreenUpdatingSetting = mApp.ScreenUpdating;
			mApp.ScreenUpdating = false;

			try {
				((_Workbook)Workbook).Activate();
				return base.GetRangeFromAddress();
			}
			catch (COMException) {
				throw;
			}
			finally {
				prevActiveWorkbook.Activate();
				mApp.ScreenUpdating = prevScreenUpdatingSetting;
			}
		}

        void ApplyConditions()
        {
            if (Conditions.Count > 0)
                Conditions.ApplyAll();
        }

        // Needed to get a reference to a workbook object that is already open in the current app.
        public string WorkbookName // To be serialized. Must be public.
        {
            get { return mWorkbookFileInfo.Name; }
        }

        // Needed to get a reference to a workbook object that is currently not open.
        public string WorkbookFullName // To be serialized. Must be public.
        {
            get { return mWorkbookFileInfo == null ? string.Empty : mWorkbookFileInfo.FullName; }
            set {
            	if(!string.IsNullOrEmpty(value)) {
            		mWorkbookFileInfo = new FileInfo(value);
            		OnPropertyChanged("WorkbookFullName");
            	}
            }
        }

        [XmlIgnore]
        public override Workbook Workbook
        {
            get { return mApp.GetWorkbookFromNames(WorkbookName, WorkbookFullName, out mWorkbookOpenedProgrammatically); }
            set
            {
                WorkbookFullName = value.FullName;
            }
        }

        public bool WorkbookOpenedProgrammatically { get { return mWorkbookOpenedProgrammatically; } }
    }
}
